﻿using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Cms;
using System;
//using T.FAS.Authority.MetaData.Entity;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using T.FAS.Runtime.DataModel.Dao;
using T.FAS.Runtime.Base.Entity;
using T.FAS.Runtime.DataModel.Plugin;
using T.FAS.Runtime.Metadata.Entity;
using T.FAS.Runtime.Metadata.Entity.DataModel;

namespace T.FAS.Runtime.DataModel.Plugin
{
    public class StateMachineRTPManager : AbsRTPMetaDataManager
    {
        private readonly StateMachineMetadataLogic _stateMachineLogic = new StateMachineMetadataLogic();
        public const string MetaDataID = DataModelConst.StateMachineMetaType;
        public const string MetaDataName = "状态机";

        public override IMetaDataContent GetMetaDataContent(string metaDataId)
        {
            if (string.IsNullOrEmpty(metaDataId))
                throw new FasException(DataModelErrorCode.NullValue, "元数据id为空");
            var machine = _stateMachineLogic.GetStateMachineMetadataByID(metaDataId);
            if (machine == null)
                throw new FasException(DataModelErrorCode.ParamError, $"未找到{MetaDataName}:{metaDataId}的元数据");
            machine.MetaDataID   = machine.ID;
            machine.MetaDataCode = machine.Code;
            machine.MetaDataName = machine.Name;
            //等待震哥更新RTPClient方法后，将数据组装部分放到Deserialize中，减少缓存Json大小以及缓存的旧数据
            //PackagingDependencyMetaData(machine);
            return machine;
        }

        public override string SerializeObject(IMetaDataContent metadata, MetadataSerializeType serializeType)
        {
            if (serializeType == MetadataSerializeType.JSON)
            {
                //(metadata as StateMachineMetadata).ClearRef();
                return JsonConvert.SerializeObject(metadata, new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                });
            }
            else
            {
                throw new NotImplementedException();
            }
        }

        public override IMetaDataContent DeserializeObject(string metaDataString, MetadataSerializeType serializeType)
        {
            if (serializeType == MetadataSerializeType.JSON)
            {
                return DeserializeObject(metaDataString, true);
            }
            else
            {
                throw new NotImplementedException();
            }
        }

        public override IMetaDataContent DeserializeObject(string metaDataString, bool isPackingData = false)
        {
            if (string.IsNullOrEmpty(metaDataString))
                throw new FasException(DataModelErrorCode.Error, $"SM反序列化Json不能为空，请检查！");
            var cdo = JsonConvert.DeserializeObject<StateMachineMetadata>(metaDataString, new JsonSerializerSettings
            {
                ReferenceLoopHandling = ReferenceLoopHandling.Ignore
            });

            if (isPackingData)
                PackagingDependencyMetaData(cdo);

            return cdo;
        }

        public override void Import(List<IMetaDataContent> contents)
        {
            var StateMachines = new List<StateMachineMetadata>();
            foreach (var metaData in contents)
            {
                var entity = metaData as StateMachineMetadata;
                if (entity == null)
                {
                    throw new FasException(DataModelErrorCode.ParamError, $"元数据类型不是{MetaDataID}, 实际类型:" + metaData.GetType().FullName);
                }

                StateMachines.Add(entity);
            }
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
                {
                    foreach (var entity in StateMachines)
                    {
                        _stateMachineLogic.DeleteStateMachineMetadata(entity.MetaDataID);
                        _stateMachineLogic.SaveStateMachineMetadata(entity);
                    }

                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.SM.ImportError, $"{MetaDataID}元数据导入失败", e);
            }
        }

        public override void Delete(List<string> IDs)
        {
            if (IDs == null)
                return;
            IDs = IDs.Where(id => id != null).ToList();
            try
            {
                using (var scope = new TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted }))
                {
                    foreach (var entity in IDs)
                    {
                        _stateMachineLogic.DeleteStateMachineMetadata(entity);
                    }

                    scope.Complete();
                }
            }
            catch (Exception e)
            {
                throw new FasException(DataModelErrorCode.SM.ImportError, $"{MetaDataName}元数据导入时删除失败", e);
            }
        }
        #region Private Funcs
        private void PackagingDependencyMetaData(IMetaDataContent metaData)
        {
            var StateMachine = metaData as StateMachineMetadata;
            if (StateMachine == null)
                return;
            if (StateMachine.Transitions != null && StateMachine.Transitions.Count > 0)
            {
                foreach (var tran in StateMachine.Transitions)
                {
                    tran.From = StateMachine.States?.FirstOrDefault(s => s.ID == tran.FromStateID);
                    tran.To = StateMachine.States?.FirstOrDefault(s => s.ID == tran.ToStateID);
                    tran.Event = StateMachine.Events?.FirstOrDefault(e => e.ID == tran.EventID);
                }
            }
            /* Todo
            //初始化状态机权限BPO对象以及OP
            if (!string.IsNullOrEmpty(StateMachine.BPOID))
            {
                StateMachine.BPO = GetMetaData<BizPermissionObject>(StateMachine.BPOID);
                if (StateMachine.BPO != null && StateMachine.Events != null)
                {
                    foreach (var tEvent in StateMachine.Events)
                    {
                        tEvent.OP = StateMachine.BPO.BizOperations.FirstOrDefault(op => op.Id == tEvent.OPID);
                    }
                }
            }*/
        }

        public override IRefSchemaEntity BuildRefSchema(IMetaDataContent metaDataContent)
        {
            if (metaDataContent is StateMachineMetadata sm)
            {
                return sm.BuildRefSchema();
            }
            else
            {
                throw new ArgumentNullException(nameof(metaDataContent));
            }
        }

        public override IEnumerable<Metadata.Entity.Term> BuildTerms(IMetaDataContent metaDataContent, IEnumerable<Metadata.Entity.Term> termList = null)
        {
            return default;
        }

        public override IRefSchemaEntity DeserializeRefSchemaEntity(string schemaEntityJson)
        {
            return JsonConvert.DeserializeObject<StateMachineRefSchemaEntity>(schemaEntityJson);
        }

        #endregion
    }
}
